/*=====================================================================

  File:      FetchStreamPush.cs
  Summary:   SQL Remote Blob Storage sample application - FetchStreamPush.
             Sample application used to fetch blob data from the 
             sample application's tables. Uses the stream Push methods.
  Date:	     July 21st, 2008

---------------------------------------------------------------------

  This file is part of the Microsoft SQL Server Code Samples.
  Copyright (C) Microsoft Corporation.  All rights reserved.

This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

======================================================= */

using System;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Text;

using Microsoft.Data.SqlRemoteBlobs;

namespace Microsoft.Samples.RemoteBlobStorage
{
    /// <summary>
    /// Sample Remote Blob Storage Application.
    /// </summary>
    public
    sealed
    class FetchStreamPush
    {
        private FetchStreamPush() { }

        public
        static
        void RunFetchStreamPush(string connectionString)
        {
            Console.WriteLine("Running the FetchStreamPush Sample");

            // Reads all blob data from the application's tables.
            //
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open();

                // Create a blob context to operate againt RBS.
                //
                SqlRemoteBlobContext blobContext = new SqlRemoteBlobContext(conn);

                // Fetch this blob using the blobId retrieved from running a query against the SearchTags field.
                // No specific collection information is required for Fetch as this information is coded into
                // the BlobId.
                //
                // Using the rbs_fn_get_blob_reference function converts the BlobId into a blob reference, which 
                // contains store specific information regarding the location of the blob. This is an optional step - 
                // passing the blob id to the SqlRemoteBlobContext.OpenBlob method will still function but will 
                // require an extra internal round trip to the database to do the conversion.
                //
                string queryBlobEntry = @" 
                                select 
                                    mssqlrbs.rbs_fn_get_blob_reference(BlobId)
                                from 
                                    ApplicationSampleTable 
                                where 
                                    SearchTags LIKE '%Sample%'
                                ";

                DataTable blobReferences = new DataTable();
                blobReferences.Locale = CultureInfo.InvariantCulture;

                // Run a query, returning all the blob IDs.
                //
                using (SqlCommand cmd = new SqlCommand(queryBlobEntry, conn))
                {
                    // Fill the blob references and close the command.
                    //
                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
                    {
                        adapter.Fill(blobReferences);
                    }
                }

                // There should be no further database access required from here on.
                // Close the database connection to confirm this is the case.
                //
                conn.Close();

                // Cycle through all the returned rows and process each in turn.
                //
                Console.WriteLine("Reading blob data (Stream Push):");
                foreach (DataRow dr in blobReferences.Rows)
                {
                    // Get the BlobReference
                    //
                    byte[] blobReference = (byte[])dr[0];

                    // Get a stream with blob data. Reuse the blobContext created initially.
                    //
                    using (SqlRemoteBlob blob = blobContext.OpenBlob(blobReference))
                    {
                        // Rather than treating the blob as a Stream, here we call a method to 'Push' the contents 
                        // of the blob into our dataStream.
                        // This method cannot be combined with calls to the Write() method on the same object.
                        //

                        // Create a MemoryStream to receive a local copy of the blob data, then output this
                        // to the console.
                        // Any kind of System.IO.Stream can be used with the .ReadToStream method, including FileStreams.
                        //
                        using (MemoryStream dataStream = new MemoryStream())
                        {
                            blob.ReadToStream(dataStream);

                            // Output a short snippet of the MemoryStream data 
                            // to the console.
                            //
                            dataStream.Seek(0, SeekOrigin.Begin);

                            byte[] readdata = new byte[256];
                            dataStream.Read(readdata, 0, readdata.Length);
                            Console.WriteLine(Encoding.Unicode.GetString(readdata));
                        }
                    }
                }
            }

            // Success
            //
        }
    }
}
